/*
 *  Copyright (C) 2012 Компания ВИТ. web: http://diasled.ru Е-mail:  vit@diasled.ru
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package ru.apertum.diasled.forms;

import ru.apertum.diasled.redactor.SensorDraw;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import org.jdesktop.application.Action;
import ru.apertum.diasled.redactor.ComboBoxOutlineModel;
import ru.apertum.diasled.cfg.Configuration;
import ru.apertum.diasled.cfg.MyPoint;
import ru.apertum.diasled.cfg.Outline;
import ru.apertum.diasled.cfg.Zone;
import ru.apertum.diasled.redactor.CZone;
import ru.apertum.diasled.redactor.OutlineTableModel;
import ru.apertum.diasled.redactor.SensorsTableModel;
import ru.vit.cfgreader.CfgReader;
import ru.vit.cfgreader.Insoles;

/**
 *
 * @author Evgeniy Egorov
 */
public class FRedactor extends javax.swing.JFrame {

    /** Creates new form FRedactor */
    public FRedactor(File conf) {
        initComponents();

        // свернем по esc
        getRootPane().registerKeyboardAction(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (isChanged() && JOptionPane.showConfirmDialog(null,
                        "Данные конфигурации были изменены. Сохранить изменения?",
                        "Сохранение посещения",
                        JOptionPane.YES_NO_OPTION) == 0) {
                    try {
                        saveFile();
                    } catch (IOException ex) {
                        System.err.println(ex);
                    }
                } else {
                    setVisible(false);
                    System.exit(0);
                }
            }
        },
                KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
                JComponent.WHEN_IN_FOCUSED_WINDOW);
        try {
            setIconImage(ImageIO.read(DiasledView.class.getResource("/ru/apertum/diasled/forms/resources/redactor.png")));
        } catch (IOException ex) {
            System.err.println(ex);
        }

        addCanvas();
        listOutlines.setModel(new ComboBoxOutlineModel(configuration.getOutlines()));

        listOutlines.addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (listOutlines.getSelectedIndex() != -1) {
                    table.setModel(new OutlineTableModel((Outline) listOutlines.getModel().getElementAt(listOutlines.getSelectedIndex())));
                    labelLeft.setText("Контур " + (listOutlines.getSelectedIndex() + 1));
                } else {
                    table.setModel(new SensorsTableModel(new LinkedList()));
                    labelLeft.setText("");
                }
                java.awt.EventQueue.invokeLater(new Runnable() {

                    public void run() {
                        canvas.repaint();
                    }
                });
            }
        });

        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            private int ind = -1;

            @Override
            public void valueChanged(ListSelectionEvent e) {

                if (table.getSelectionModel().getLeadSelectionIndex() != ind) {
                    //System.out.println(e.getFirstIndex() + " - " + e.getLastIndex() + "; " + table.getSelectionModel().getLeadSelectionIndex() + " = "
                    //        + table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 0) + " _ "
                    //        + table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 1));
                    java.awt.EventQueue.invokeLater(new Runnable() {

                        public void run() {
                            canvas.repaint();
                        }
                    });
                }
                ind = table.getSelectionModel().getLeadSelectionIndex();
            }
        });
        table.addFocusListener(new FocusListener() {

            @Override
            public void focusGained(FocusEvent e) {
                if (e.paramString().indexOf("[Table.editor,") != -1) {
                    java.awt.EventQueue.invokeLater(new Runnable() {

                        public void run() {
                            canvas.repaint();
                        }
                    });
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
            }
        });

    }
    private boolean changed;

    private boolean isChanged() {
        return changed;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        popupMenuOutline = new javax.swing.JPopupMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenuItem13 = new javax.swing.JMenuItem();
        popupMenuTableOutline = new javax.swing.JPopupMenu();
        jMenuItem2 = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        jMenuItem3 = new javax.swing.JMenuItem();
        jSeparator3 = new javax.swing.JPopupMenu.Separator();
        jMenuItem14 = new javax.swing.JMenuItem();
        jMenuItem15 = new javax.swing.JMenuItem();
        buttonGroupOutSenc = new javax.swing.ButtonGroup();
        popupMenuTableSensors = new javax.swing.JPopupMenu();
        jMenuItem4 = new javax.swing.JMenuItem();
        jMenuItem10 = new javax.swing.JMenuItem();
        jMenuItem12 = new javax.swing.JMenuItem();
        PanelStatus = new javax.swing.JPanel();
        labelLeft = new javax.swing.JLabel();
        labelDraw = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        listOutlines = new javax.swing.JList();
        buttonFinaliseTrace = new javax.swing.JButton();
        jButton1 = new javax.swing.JButton();
        jPanel4 = new javax.swing.JPanel();
        radioButtonOutline = new javax.swing.JRadioButton();
        radioButtonSensor = new javax.swing.JRadioButton();
        jPanel5 = new javax.swing.JPanel();
        jButton2 = new javax.swing.JButton();
        sliderScale = new javax.swing.JSlider();
        buttonCenter = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        panelDraw = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        table = new javax.swing.JTable();
        jMenuBar1 = new javax.swing.JMenuBar();
        menuFile = new javax.swing.JMenu();
        jMenuItem5 = new javax.swing.JMenuItem();
        jMenuItem6 = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        jMenuItem7 = new javax.swing.JMenuItem();
        menuEdit = new javax.swing.JMenu();
        jMenuItem8 = new javax.swing.JMenuItem();
        jMenuItem9 = new javax.swing.JMenuItem();
        jMenuItem11 = new javax.swing.JMenuItem();

        popupMenuOutline.setName("popupMenuOutline"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getActionMap(FRedactor.class, this);
        jMenuItem1.setAction(actionMap.get("removeOutline")); // NOI18N
        jMenuItem1.setName("jMenuItem1"); // NOI18N
        popupMenuOutline.add(jMenuItem1);

        jMenuItem13.setAction(actionMap.get("editOutlineZone")); // NOI18N
        jMenuItem13.setName("jMenuItem13"); // NOI18N
        popupMenuOutline.add(jMenuItem13);

        popupMenuTableOutline.setName("popupMenuTableOutline"); // NOI18N

        jMenuItem2.setAction(actionMap.get("insertNodeToRoute")); // NOI18N
        jMenuItem2.setName("jMenuItem2"); // NOI18N
        popupMenuTableOutline.add(jMenuItem2);

        jSeparator1.setName("jSeparator1"); // NOI18N
        popupMenuTableOutline.add(jSeparator1);

        jMenuItem3.setAction(actionMap.get("removeRouteNode")); // NOI18N
        jMenuItem3.setName("jMenuItem3"); // NOI18N
        popupMenuTableOutline.add(jMenuItem3);

        jSeparator3.setName("jSeparator3"); // NOI18N
        popupMenuTableOutline.add(jSeparator3);

        jMenuItem14.setAction(actionMap.get("addFirstZonePoint")); // NOI18N
        jMenuItem14.setName("jMenuItem14"); // NOI18N
        popupMenuTableOutline.add(jMenuItem14);

        jMenuItem15.setAction(actionMap.get("addLastZonePoint")); // NOI18N
        jMenuItem15.setName("jMenuItem15"); // NOI18N
        popupMenuTableOutline.add(jMenuItem15);

        popupMenuTableSensors.setName("popupMenuTableSensors"); // NOI18N

        jMenuItem4.setAction(actionMap.get("removeSensor")); // NOI18N
        jMenuItem4.setName("jMenuItem4"); // NOI18N
        popupMenuTableSensors.add(jMenuItem4);

        jMenuItem10.setAction(actionMap.get("openTarConfig")); // NOI18N
        jMenuItem10.setName("jMenuItem10"); // NOI18N
        popupMenuTableSensors.add(jMenuItem10);

        jMenuItem12.setAction(actionMap.get("editZones")); // NOI18N
        jMenuItem12.setName("jMenuItem12"); // NOI18N
        popupMenuTableSensors.add(jMenuItem12);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getResourceMap(FRedactor.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N

        PanelStatus.setBorder(new javax.swing.border.MatteBorder(null));
        PanelStatus.setName("PanelStatus"); // NOI18N

        labelLeft.setText(resourceMap.getString("labelLeft.text")); // NOI18N
        labelLeft.setName("labelLeft"); // NOI18N

        labelDraw.setText(resourceMap.getString("labelDraw.text")); // NOI18N
        labelDraw.setName("labelDraw"); // NOI18N

        javax.swing.GroupLayout PanelStatusLayout = new javax.swing.GroupLayout(PanelStatus);
        PanelStatus.setLayout(PanelStatusLayout);
        PanelStatusLayout.setHorizontalGroup(
            PanelStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(PanelStatusLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(labelLeft, javax.swing.GroupLayout.PREFERRED_SIZE, 186, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(labelDraw)
                .addContainerGap(745, Short.MAX_VALUE))
        );
        PanelStatusLayout.setVerticalGroup(
            PanelStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(PanelStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(labelLeft, javax.swing.GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE)
                .addComponent(labelDraw, javax.swing.GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE))
        );

        jPanel2.setBorder(new javax.swing.border.MatteBorder(null));
        jPanel2.setName("jPanel2"); // NOI18N

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jPanel3.border.title"))); // NOI18N
        jPanel3.setName("jPanel3"); // NOI18N

        jScrollPane2.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jScrollPane2.border.title"))); // NOI18N
        jScrollPane2.setName("jScrollPane2"); // NOI18N

        listOutlines.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        listOutlines.setComponentPopupMenu(popupMenuOutline);
        listOutlines.setName("listOutlines"); // NOI18N
        listOutlines.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                listOutlinesMouseClicked(evt);
            }
        });
        jScrollPane2.setViewportView(listOutlines);

        buttonFinaliseTrace.setText(resourceMap.getString("buttonFinaliseTrace.text")); // NOI18N
        buttonFinaliseTrace.setName("buttonFinaliseTrace"); // NOI18N
        buttonFinaliseTrace.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonFinaliseTraceActionPerformed(evt);
            }
        });

        jButton1.setAction(actionMap.get("RedoOutline")); // NOI18N
        jButton1.setName("jButton1"); // NOI18N

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(buttonFinaliseTrace)
                    .addComponent(jButton1)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 176, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addComponent(buttonFinaliseTrace)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 110, Short.MAX_VALUE))
        );

        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jPanel4.border.title"))); // NOI18N
        jPanel4.setName("jPanel4"); // NOI18N

        buttonGroupOutSenc.add(radioButtonOutline);
        radioButtonOutline.setSelected(true);
        radioButtonOutline.setText(resourceMap.getString("radioButtonOutline.text")); // NOI18N
        radioButtonOutline.setName("radioButtonOutline"); // NOI18N
        radioButtonOutline.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioButtonOutlineActionPerformed(evt);
            }
        });

        buttonGroupOutSenc.add(radioButtonSensor);
        radioButtonSensor.setText(resourceMap.getString("radioButtonSensor.text")); // NOI18N
        radioButtonSensor.setName("radioButtonSensor"); // NOI18N
        radioButtonSensor.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioButtonOutlineActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(radioButtonOutline)
                    .addComponent(radioButtonSensor))
                .addContainerGap(109, Short.MAX_VALUE))
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addComponent(radioButtonOutline)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(radioButtonSensor))
        );

        jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jPanel5.border.title"))); // NOI18N
        jPanel5.setName("jPanel5"); // NOI18N

        jButton2.setAction(actionMap.get("RedoSensor")); // NOI18N
        jButton2.setName("jButton2"); // NOI18N

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addComponent(jButton2)
                .addContainerGap(15, Short.MAX_VALUE))
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addComponent(jButton2)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        sliderScale.setMajorTickSpacing(20);
        sliderScale.setMinimum(-20);
        sliderScale.setMinorTickSpacing(5);
        sliderScale.setPaintLabels(true);
        sliderScale.setPaintTicks(true);
        sliderScale.setValue(0);
        sliderScale.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("sliderScale.border.title"))); // NOI18N
        sliderScale.setName("sliderScale"); // NOI18N
        sliderScale.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sliderScaleStateChanged(evt);
            }
        });

        buttonCenter.setText(resourceMap.getString("buttonCenter.text")); // NOI18N
        buttonCenter.setName("buttonCenter"); // NOI18N
        buttonCenter.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonCenterActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel5, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(sliderScale, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 198, Short.MAX_VALUE)
                    .addComponent(buttonCenter, javax.swing.GroupLayout.Alignment.LEADING))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(sliderScale, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(buttonCenter)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 244, Short.MAX_VALUE)
                .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        jPanel1.setBackground(resourceMap.getColor("jPanel1.background")); // NOI18N
        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setName("jPanel1"); // NOI18N

        panelDraw.setBackground(resourceMap.getColor("panelDraw.background")); // NOI18N
        panelDraw.setBorder(javax.swing.BorderFactory.createLineBorder(resourceMap.getColor("panelDraw.border.lineColor"), 5)); // NOI18N
        panelDraw.setName("panelDraw"); // NOI18N
        panelDraw.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                panelDrawMouseMoved(evt);
            }
        });

        javax.swing.GroupLayout panelDrawLayout = new javax.swing.GroupLayout(panelDraw);
        panelDraw.setLayout(panelDrawLayout);
        panelDrawLayout.setHorizontalGroup(
            panelDrawLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 690, Short.MAX_VALUE)
        );
        panelDrawLayout.setVerticalGroup(
            panelDrawLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 682, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(panelDraw, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(panelDraw, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        table.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "X", "Y"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.Integer.class, java.lang.Integer.class
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
        });
        table.setComponentPopupMenu(popupMenuTableOutline);
        table.setName("table"); // NOI18N
        table.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        jScrollPane1.setViewportView(table);
        table.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("table.columnModel.title0")); // NOI18N
        table.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("table.columnModel.title1")); // NOI18N

        jMenuBar1.setName("jMenuBar1"); // NOI18N

        menuFile.setText(resourceMap.getString("menuFile.text")); // NOI18N
        menuFile.setName("menuFile"); // NOI18N

        jMenuItem5.setAction(actionMap.get("openFile")); // NOI18N
        jMenuItem5.setName("jMenuItem5"); // NOI18N
        menuFile.add(jMenuItem5);

        jMenuItem6.setAction(actionMap.get("saveFile")); // NOI18N
        jMenuItem6.setName("jMenuItem6"); // NOI18N
        menuFile.add(jMenuItem6);

        jSeparator2.setName("jSeparator2"); // NOI18N
        menuFile.add(jSeparator2);

        jMenuItem7.setAction(actionMap.get("quit")); // NOI18N
        jMenuItem7.setName("jMenuItem7"); // NOI18N
        menuFile.add(jMenuItem7);

        jMenuBar1.add(menuFile);

        menuEdit.setText(resourceMap.getString("menuEdit.text")); // NOI18N
        menuEdit.setName("menuEdit"); // NOI18N

        jMenuItem8.setAction(actionMap.get("configParams")); // NOI18N
        jMenuItem8.setName("jMenuItem8"); // NOI18N
        menuEdit.add(jMenuItem8);

        jMenuItem9.setAction(actionMap.get("openTarConfig")); // NOI18N
        jMenuItem9.setName("jMenuItem9"); // NOI18N
        menuEdit.add(jMenuItem9);

        jMenuItem11.setAction(actionMap.get("showColorScaleEditor")); // NOI18N
        jMenuItem11.setName("jMenuItem11"); // NOI18N
        menuEdit.add(jMenuItem11);

        jMenuBar1.add(menuEdit);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(PanelStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 197, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 694, Short.MAX_VALUE)
                    .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(PanelStatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void panelDrawMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_panelDrawMouseMoved
        labelDraw.setText("X=" + evt.getPoint().x + "  Y=" + evt.getPoint().y);
    }//GEN-LAST:event_panelDrawMouseMoved

    private void buttonFinaliseTraceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonFinaliseTraceActionPerformed
        if (!configuration.getOutlines().isEmpty()) {
            final Outline trace = configuration.getOutlines().getLast();
            trace.getRoute().add(trace.getRoute().getFirst());
            changed = true;
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    canvas.repaint();
                }
            });
        }
    }//GEN-LAST:event_buttonFinaliseTraceActionPerformed

    private void radioButtonOutlineActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioButtonOutlineActionPerformed
        if (radioButtonOutline.isSelected()) {
            listOutlines.getListSelectionListeners()[0].valueChanged(null);
            table.setComponentPopupMenu(popupMenuTableOutline);
        } else {
            table.setModel(new SensorsTableModel(configuration.getSensors()));
            table.setComponentPopupMenu(popupMenuTableSensors);
            labelLeft.setText("Таблица сенсоров " + configuration.getSensors().size() + "шт.");
        }
    }//GEN-LAST:event_radioButtonOutlineActionPerformed

    private void sliderScaleStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sliderScaleStateChanged

        scale = sliderScale.getValue() / 1.25 * 0.05 + 1;
        if (scale < -1) {
            scale = -1;
        }
        if (scale > 5) {
            scale = 5;
        }
        //dx = (int) ((panelDraw.getWidth() / 2 - x * scale) / scale);
        //dy = (int) ((panelDraw.getHeight() / 2 - y * scale) / scale);
        //int cx = panelDraw.getWidth() / 2;
        //int cy = panelDraw.getHeight() / 2;
        //dx = (int) ((cx - (cx - 8) * scale) / scale);
        //dy = (int) ((cy - (cy - 8) * scale) / scale);
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                canvas.repaint();
            }
        });

    }//GEN-LAST:event_sliderScaleStateChanged

    private void buttonCenterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCenterActionPerformed
        int min_x = 100000;
        int max_x = -100000;
        int min_y = 100000;
        int max_y = -100000;
        for (Outline outline : configuration.getOutlines()) {
            for (MyPoint point : outline.getRoute()) {
                if (min_x > point.x) {
                    min_x = point.x;
                }
                if (max_x < point.x) {
                    max_x = point.x;
                }
                if (min_y > point.y) {
                    min_y = point.y;
                }
                if (max_y < point.y) {
                    max_y = point.y;
                }
            }
        }
        for (SensorDraw sensor : configuration.getSensors()) {
            if (min_x > sensor.x) {
                min_x = sensor.x;
            }
            if (max_x < sensor.x) {
                max_x = sensor.x;
            }
            if (min_y > sensor.y) {
                min_y = sensor.y;
            }
            if (max_y < sensor.y) {
                max_y = sensor.y;
            }
        }
        int x = (min_x + max_x) / 2;
        int y = (min_y + max_y) / 2;
        //System.out.println(min_x + " " + max_x + " " + min_y + " " + max_y + " ");

        //sx = x - dx;
        //sy = y - dy;

        dx = (int) ((panelDraw.getWidth() / 2 - x * scale) / scale);
        dy = (int) ((panelDraw.getHeight() / 2 - y * scale) / scale);
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                canvas.repaint();
            }
        });

    }//GEN-LAST:event_buttonCenterActionPerformed

    private void listOutlinesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_listOutlinesMouseClicked
        if (evt.getClickCount() == 2) {
            editOutlineZone();
        }
    }//GEN-LAST:event_listOutlinesMouseClicked

    @Action
    public void removeOutline() {
        if (listOutlines.getSelectedIndex() != -1 && JOptionPane.showConfirmDialog(null,
                "Удалить контур " + (listOutlines.getSelectedIndex() + 1) + " на всегда?",
                "Удаление контура",
                JOptionPane.YES_NO_OPTION) == 0) {
            configuration.getOutlines().remove(listOutlines.getModel().getElementAt(listOutlines.getSelectedIndex()));
            listOutlines.setModel(new ComboBoxOutlineModel(configuration.getOutlines()));
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    canvas.repaint();
                }
            });
        }
    }

    @Action
    public void insertNodeToRoute() {
        if (table.getSelectionModel().getLeadSelectionIndex() != -1 && table.getModel() instanceof OutlineTableModel) {

            int x = (int) table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 0);
            int y = (int) table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 1);

            int s = table.getSelectionModel().getLeadSelectionIndex() + 1;
            ((OutlineTableModel) (table.getModel())).add(s, new MyPoint(x + 5, y + 5));
            ((OutlineTableModel) (table.getModel())).fireTableDataChanged();
            table.getSelectionModel().setSelectionInterval(s, s);
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    canvas.repaint();
                }
            });
        }
    }

    @Action
    public void removeRouteNode() {
        if (table.getSelectionModel().getLeadSelectionIndex() != -1 && table.getModel() instanceof OutlineTableModel) {
            final ArrayList<Point> ap = new ArrayList<>();
            for (int i : table.getSelectedRows()) {
                ap.add(new Point((int) table.getModel().getValueAt(i, 0), (int) table.getModel().getValueAt(i, 1)));
            }
            for (Point point : ap) {
                ((OutlineTableModel) (table.getModel())).remove(point);
            }
            ((OutlineTableModel) (table.getModel())).fireTableDataChanged();
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    canvas.repaint();
                }
            });
        }
    }

    @Action
    public void RedoOutline() {
        if (!configuration.getOutlines().isEmpty()) {
            Outline trace = configuration.getOutlines().getLast();
            if (!trace.getRoute().isEmpty()) {
                trace.getRoute().removeLast();
                changed = true;
                java.awt.EventQueue.invokeLater(new Runnable() {

                    public void run() {
                        canvas.repaint();
                    }
                });
            }
        }
    }

    @Action
    public void RedoSensor() {
        if (!configuration.getSensors().isEmpty()) {
            configuration.getSensors().removeLast();
            ((SensorsTableModel) (table.getModel())).fireTableDataChanged();
            changed = true;
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    canvas.repaint();
                }
            });
        }
    }

    @Action
    public void removeSensor() {
        if (!configuration.getSensors().isEmpty() && table.getSelectionModel().getLeadSelectionIndex() != -1 && table.getModel() instanceof SensorsTableModel) {
            final ArrayList<SensorDraw> ap = new ArrayList<>();
            for (int i : table.getSelectedRows()) {
                ap.add(new SensorDraw((int) table.getModel().getValueAt(i, 0), (int) table.getModel().getValueAt(i, 1)));
            }
            for (SensorDraw point : ap) {
                ((SensorsTableModel) (table.getModel())).remove(point);
            }
            ((SensorsTableModel) (table.getModel())).fireTableDataChanged();
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    canvas.repaint();
                }
            });
        }
    }

    @Action
    public void openFile() throws IOException {
        final JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Выберите файл конфигурации");
        fc.setFileFilter(new FileFilter() {

            @Override
            public boolean accept(File f) {
                return !f.isFile() || f.getAbsolutePath().endsWith(".cfg") || f.getAbsolutePath().endsWith(".CFG");
            }

            @Override
            public String getDescription() {
                return "Конфигурация для версии 1.0 (*.cfg)";
            }
        });
        fc.setFileFilter(new FileFilter() {

            @Override
            public boolean accept(File f) {
                return !f.isFile() || f.getAbsolutePath().endsWith(".vit") || f.getAbsolutePath().endsWith(".VIT");
            }

            @Override
            public String getDescription() {
                return "Конфигурация Диаслед (*.vit)";
            }
        });

        fc.setCurrentDirectory(new File("config"));
        if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            if (file.getAbsolutePath().endsWith(".cfg") || file.getAbsolutePath().endsWith(".CFG")) {
                Insoles system = new Insoles();
                CfgReader cfg = new CfgReader(file, system);
                cfg.readCfg();
                cfg.readCtr();
                cfg.readTar();
                configuration = Configuration.cfg(system, file.getName().substring(0, file.getName().indexOf(".")));
            } else {
                configuration = Configuration.load(file);
            }
            listOutlines.setModel(new ComboBoxOutlineModel(configuration.getOutlines()));
            if (listOutlines.getModel().getSize() != 0) {
                listOutlines.setSelectedIndex(0);
            }
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    canvas.repaint();
                }
            });
        }
    }

    @Action
    public void saveFile() throws IOException {
        final JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Сохранение файла конфигурации");
        fc.setFileFilter(new FileFilter() {

            @Override
            public boolean accept(File f) {
                return !f.isFile() || f.getAbsolutePath().endsWith(".vit") || f.getAbsolutePath().endsWith(".VIT");
            }

            @Override
            public String getDescription() {
                return "Конфигурация Диаслед";
            }
        });
        fc.setCurrentDirectory(new File("config"));
        fc.setSelectedFile(new File(configuration.getSystemName()));
        fc.setDialogType(JFileChooser.SAVE_DIALOG);
        if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            //This is where a real application would open the file.
            if (!file.getAbsolutePath().endsWith(".vit") && !file.getAbsolutePath().endsWith(".VIT")) {
                file = new File(file.getAbsoluteFile() + ".vit");
            }
            configuration.save(file);
            changed = false;
            JOptionPane.showMessageDialog(this,
                    "Файл конфигурации сохранен.",
                    "Сохранение",
                    JOptionPane.INFORMATION_MESSAGE);
        }
    }

    @Action
    public void configParams() {

        final FRedactorParams rp = FRedactorParams.getInstance();
        rp.loadConfig(configuration);
        rp.setLocationRelativeTo(null);
        rp.setVisible(true);
        if (rp.isOK()) {
            rp.saveConfig(configuration);
        }
    }

    @Action
    public void openTarConfig() {
        if (table.getModel() instanceof SensorsTableModel && table.getSelectionModel().getLeadSelectionIndex() != -1) {
            int x = (int) table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 0);
            int y = (int) table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 1);
            SensorDraw sd = null;
            for (SensorDraw sensor : configuration.getSensors()) {
                if (sensor.x == x && sensor.y == y) {
                    sd = sensor;
                    break;
                }
            }
            if (sd == null) {
                return;
            }
            final FRedactorTar rp = FRedactorTar.getInstance();
            rp.loadConfig(sd);
            rp.setLocationRelativeTo(null);
            rp.setVisible(true);
            if (rp.isOK()) {
                rp.saveConfig(sd);
            }
        }
    }

    @Action
    public void editZones() {
        if (table.getModel() instanceof SensorsTableModel && table.getSelectionModel().getLeadSelectionIndex() != -1) {
            int x = (int) table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 0);
            int y = (int) table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 1);
            SensorDraw sd = null;
            for (SensorDraw sensor : configuration.getSensors()) {
                if (sensor.x == x && sensor.y == y) {
                    sd = sensor;
                    break;
                }
            }
            if (sd == null) {
                return;
            }
            final FEditorSensorZone rp = FEditorSensorZone.getInstance();
            rp.loadConfig(sd);
            rp.setLocationRelativeTo(null);
            rp.setVisible(true);
            if (rp.isOK()) {
                rp.saveConfig(sd);
            }
        }
    }

    @Action
    public void showColorScaleEditor() {
        FColorScaleEditor.getInstance(configuration).setVisible(true);
    }

    @Action
    public void editOutlineZone() {
        if (listOutlines.getSelectedIndex() != -1) {
            final FOutlineZone oz = FOutlineZone.getInstance();
            oz.loadConfig((Outline) listOutlines.getModel().getElementAt(listOutlines.getSelectedIndex()), canvas);
            oz.setLocationRelativeTo(null);
            oz.setVisible(true);
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(final String args[]) {
        try {
            // Set System L&F
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            // handle exception
        }

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                File f = null;
                if (args.length > 0) {
                    f = new File(args[0]);
                    if (!f.exists()) {
                        f = null;
                    }
                }
                final FRedactor r = new FRedactor(f);
                r.setLocationRelativeTo(null);
                r.setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel PanelStatus;
    private javax.swing.JButton buttonCenter;
    private javax.swing.JButton buttonFinaliseTrace;
    private javax.swing.ButtonGroup buttonGroupOutSenc;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem10;
    private javax.swing.JMenuItem jMenuItem11;
    private javax.swing.JMenuItem jMenuItem12;
    private javax.swing.JMenuItem jMenuItem13;
    private javax.swing.JMenuItem jMenuItem14;
    private javax.swing.JMenuItem jMenuItem15;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JMenuItem jMenuItem4;
    private javax.swing.JMenuItem jMenuItem5;
    private javax.swing.JMenuItem jMenuItem6;
    private javax.swing.JMenuItem jMenuItem7;
    private javax.swing.JMenuItem jMenuItem8;
    private javax.swing.JMenuItem jMenuItem9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private javax.swing.JPopupMenu.Separator jSeparator3;
    private javax.swing.JLabel labelDraw;
    private javax.swing.JLabel labelLeft;
    private javax.swing.JList listOutlines;
    private javax.swing.JMenu menuEdit;
    private javax.swing.JMenu menuFile;
    private javax.swing.JPanel panelDraw;
    private javax.swing.JPopupMenu popupMenuOutline;
    private javax.swing.JPopupMenu popupMenuTableOutline;
    private javax.swing.JPopupMenu popupMenuTableSensors;
    private javax.swing.JRadioButton radioButtonOutline;
    private javax.swing.JRadioButton radioButtonSensor;
    private javax.swing.JSlider sliderScale;
    private javax.swing.JTable table;
    // End of variables declaration//GEN-END:variables
    Canvas canvas;

    private void addCanvas() {
        panelDraw.removeAll();
        canvas = new Canvas() {

            @Override
            public void paint(Graphics g) {
                // сетка
                g.setColor(new Color(245, 245, 245));
                for (int x = 0; x < getWidth(); x = x + 20) {
                    g.drawLine(x, 0, x, getHeight());
                }
                for (int y = 0; y < getHeight(); y = y + 20) {
                    g.drawLine(0, y, getWidth(), y);
                }

                ((Graphics2D) g).scale(scale, scale);
                ((Graphics2D) g).translate(dx, dy);


                // выделения
                final boolean f = table.getModel() instanceof SensorsTableModel;
                if (table.getSelectionModel().getLeadSelectionIndex() != -1) {
                    g.setColor(new Color(230, 230, 230));
                    int x = (int) table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 0);
                    int y = (int) table.getModel().getValueAt(table.getSelectionModel().getLeadSelectionIndex(), 1);
                    g.drawLine(x, 0 - dy, x, getHeight());
                    g.drawLine(0 - dx, y, getWidth(), y);
                    g.setColor(new Color(245, 0, 0));
                    if (!f) {
                        g.drawOval(x - 4, y - 4, 8, 8);
                    }

                    for (int i : table.getSelectedRows()) {
                        x = (int) table.getModel().getValueAt(i, 0);
                        y = (int) table.getModel().getValueAt(i, 1);
                        if (f) {
                            // g.drawOval(x - SensorDraw.RAD - 0, y - SensorDraw.RAD - 0, (SensorDraw.RAD + 0) * 2, (SensorDraw.RAD + 0) * 2);
                            g.drawOval(x - SensorDraw.RAD - 1, y - SensorDraw.RAD - 1, (SensorDraw.RAD + 1) * 2, (SensorDraw.RAD + 1) * 2);
                            /*
                            int ii = 0;
                            for (CZone z : configuration.findSensor(x, y).getZone()) {
                            g.drawString("" + z.getZone() + "-" + z.getCoeff(), x + SensorDraw.RAD + 2, y - SensorDraw.RAD + ii * 10);
                            ii++;
                            }
                             * 
                             */
                        } else {
                            g.drawOval(x - 4, y - 4, 8, 8);
                        }
                    }
                }


                // контуры 
                for (Outline route : configuration.getOutlines()) {
                    // цвер контура
                    if (!route.getRoute().isEmpty() && route.getRoute().size() > 1 && route.getRoute().getFirst().equals(route.getRoute().getLast())) {
                        if (listOutlines.getSelectedIndex() != -1 && listOutlines.getModel().getElementAt(listOutlines.getSelectedIndex()).equals(route)) {
                            g.setColor(new Color(255, 0, 0));
                        } else {
                            g.setColor(new Color(0, 0, 255));
                        }
                    } else {
                        g.setColor(new Color(255, 0, 0));
                    }
                    MyPoint first = null;
                    if (route.getRoute().size() == 1) {
                        // если в контуре только одна первая точка
                        g.drawOval(route.getRoute().getFirst().x - 3, route.getRoute().getFirst().y - 3, 6, 6);
                    } else {
                        // рисуем ломаную
                        for (MyPoint point : route.getRoute()) {

                            if (first == null) {
                                first = point;
                            } else {
                                g.drawLine(first.x, first.y, point.x, point.y);
                                first = point;
                            }
                        }

                    }
                }
                // зоны в контурах
                for (Outline route : configuration.getOutlines()) {
                    Zone zonesel = null;
                    for (Zone zone : route.getZone()) {
                        if (FOutlineZone.getInstance().getListZone().getSelectedValue() != null && FOutlineZone.getInstance().getListZone().getSelectedValue().getNum() == zone.getNum()) {
                            zonesel = zone;
                            continue;
                        } else {
                            g.setColor(new Color(0, 150, 0));
                        }
                        // рисуем ломаную
                        MyPoint first = null;
                        for (MyPoint point : zone.getRoute()) {
                            if (first == null) {
                                first = point;
                            } else {
                                g.drawLine(first.x, first.y, point.x, point.y);
                                first = point;
                            }
                        }
                    }
                    if (zonesel != null) {
                        // рисуем ломаную
                        g.setColor(new Color(255, 0, 250));
                        MyPoint first = null;
                        for (MyPoint point : zonesel.getRoute()) {
                            if (first == null) {
                                first = point;
                            } else {
                                g.drawLine(first.x, first.y, point.x, point.y);
                                first = point;
                            }
                        }
                    }
                }
                // сенсоры
                g.setColor(new Color(155, 0, 0));
                for (SensorDraw sensor : configuration.getSensors()) {
                    sensor.draw(g);
                }
                g.setColor(new Color(0, 155, 5));
                if (table.getSelectionModel().getLeadSelectionIndex() != -1) {
                    for (int i : table.getSelectedRows()) {
                        final int x = (int) table.getModel().getValueAt(i, 0);
                        final int y = (int) table.getModel().getValueAt(i, 1);
                        if (f) {
                            int ii = 0;
                            for (CZone z : configuration.findSensor(x, y).getZone()) {
                                g.drawString("" + z.getZone() + "-" + z.getCoeff(), x + SensorDraw.RAD + 1, y - SensorDraw.RAD + ii * 10);
                                ii++;
                            }
                        }
                    }
                }
            }
        };


        canvas.setBounds(0, 0, 2000, 1250);
        panelDraw.add(canvas);

        canvas.addMouseMotionListener(new MouseMotionListener() {

            @Override
            public void mouseDragged(MouseEvent evt) {
                labelDraw.setText("X=" + evt.getPoint().x + "  Y=" + evt.getPoint().y + " Dragged");
                if (dragg) {

                    dx = -sx + evt.getX();
                    dy = -sy + evt.getY();
                    java.awt.EventQueue.invokeLater(new Runnable() {

                        public void run() {
                            canvas.repaint();
                        }
                    });
                }
            }

            @Override
            public void mouseMoved(MouseEvent evt) {
                labelDraw.setText("X=" + evt.getPoint().x + "  Y=" + evt.getPoint().y + " Moved");
            }
        });
        canvas.addMouseListener(new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
            }

            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON3) {
                    sx = e.getPoint().x - dx;
                    sy = e.getPoint().y - dy;
                    dragg = true;
                    return;
                }
                if (FOutlineZone.getInstance().isVisible()) {
                    FOutlineZone.getInstance().addLastPOint(new MyPoint((int) (e.getPoint().x / scale) - dx, (int) (e.getPoint().y / scale) - dy));
                    java.awt.EventQueue.invokeLater(new Runnable() {

                        public void run() {
                            canvas.repaint();
                        }
                    });
                    return;
                }
                if (radioButtonOutline.isSelected()) {
                    if (configuration.getOutlines().isEmpty()) {
                        configuration.getOutlines().add(new Outline());
                        listOutlines.setModel(new ComboBoxOutlineModel(configuration.getOutlines()));
                    }
                    Outline trace = configuration.getOutlines().getLast();
                    if (!trace.getRoute().isEmpty() && trace.getRoute().size() > 1 && trace.getRoute().getFirst().equals(trace.getRoute().getLast())) {
                        configuration.getOutlines().add(new Outline());
                        listOutlines.setModel(new ComboBoxOutlineModel(configuration.getOutlines()));
                        trace = configuration.getOutlines().getLast();
                    }
                    trace.getRoute().add(new MyPoint((int) (e.getPoint().x / scale) - dx, (int) (e.getPoint().y / scale) - dy));
                    changed = true;

                    java.awt.EventQueue.invokeLater(new Runnable() {

                        public void run() {
                            canvas.repaint();
                        }
                    });
                }
                if (radioButtonSensor.isSelected()) {
                    final SensorDraw sensor = new SensorDraw((int) (e.getPoint().x / scale) - dx, (int) (e.getPoint().y / scale) - dy);
                    configuration.getSensors().add(sensor);
                    //sensor.setPhisicalNum(configuration.getSensors().size());
                    sensor.setLogicalNum(configuration.getSensors().size() - 1);
                    ((SensorsTableModel) (table.getModel())).fireTableDataChanged();
                    changed = true;
                    java.awt.EventQueue.invokeLater(new Runnable() {

                        public void run() {
                            canvas.repaint();
                        }
                    });
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                dragg = false;
            }

            @Override
            public void mouseEntered(MouseEvent e) {
            }

            @Override
            public void mouseExited(MouseEvent e) {
            }
        });



        canvas.addMouseWheelListener(new MouseWheelListener() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                scale = scale + e.getWheelRotation() * 0.05;
                if (scale < -1) {
                    scale = -1;
                }
                if (scale > 5) {
                    scale = 5;
                }
                sliderScale.setValue((int) ((scale - 1) * 20 * 1.25));
            }
        });
    }

    @Action
    public void addFirstZonePoint() {
        if (FOutlineZone.getInstance().isVisible()
                && table.getSelectionModel().getLeadSelectionIndex() != -1
                && table.getModel() instanceof OutlineTableModel
                && table.getSelectedRows().length == 1) {

            for (int i : table.getSelectedRows()) {
                FOutlineZone.getInstance().addFirstPOint(new MyPoint((int) table.getModel().getValueAt(i, 0), (int) table.getModel().getValueAt(i, 1)));
            }
        }
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                canvas.repaint();
            }
        });
    }

    @Action
    public void addLastZonePoint() {
        if (FOutlineZone.getInstance().isVisible()
                && table.getSelectionModel().getLeadSelectionIndex() != -1
                && table.getModel() instanceof OutlineTableModel
                && table.getSelectedRows().length == 1) {

            for (int i : table.getSelectedRows()) {
                FOutlineZone.getInstance().addLastPOint(new MyPoint((int) table.getModel().getValueAt(i, 0), (int) table.getModel().getValueAt(i, 1)));
            }
        }
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                canvas.repaint();
            }
        });
    }
    int sx, sy, dx, dy;
    boolean dragg;
    /**
     * Коэфициент увеличения
     */
    private double scale = 1;
    /**
     * Конфигурация
     */
    private Configuration configuration = new Configuration();
}
